package com.homer.android.sdk.command.device.common;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpStatus;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.homer.android.sdk.devcie.IEspDevice;
import com.homer.android.sdk.devcie.bulider.BEspDevice;
import com.homer.android.sdk.group.IEspGroup;
import com.homer.android.sdk.group.bulider.BEspGroup;
import com.homer.android.sdk.type.devcie.state.EspDeviceState;
import com.homer.android.sdk.type.net.HeaderPair;
import com.homer.android.sdk.type.user.builder.BEspUser;
import com.homer.android.sdk.util.BSSIDUtil;
import com.homer.android.sdk.util.MeshUtil;
import com.homer.android.sdk.util.TimeUtil;
import com.homer.iot.esptouch.base.api.EspBaseApiUtil;
import com.homer.iot.esptouch.udp.EspDeviceType;



public class EspCommandDeviceSynchronizeInternet implements IEspCommandDeviceSynchronizeInternet
{
    private final static Logger log = Logger.getLogger(EspCommandDeviceSynchronizeInternet.class);
    
    private static final long ONLINE_TIMEOUT_PLUG = 60 * TimeUtil.ONE_SECOND_LONG_VALUE;
    
    private static final long ONLINE_TIMEOUT_LIGHT = 60 * TimeUtil.ONE_SECOND_LONG_VALUE;
    
    private static final long ONLINE_TIMEOUT_TEMPERATURE = 5 * TimeUtil.ONE_MINUTE_LONG_VALUE;
    
    private static final long ONLINE_TIMEOUT_GAS_SIREN = 5 * TimeUtil.ONE_MINUTE_LONG_VALUE;
    
    private static final long ONLINE_TIMEOUT_REMOTE = 60 * TimeUtil.ONE_SECOND_LONG_VALUE;
    
    private static final long ONLINE_TIMEOUT_PLUGS = 60 * TimeUtil.ONE_SECOND_LONG_VALUE;
    
    private static final long ONLINE_TIMEOUT_VOLTAGE = 60 * TimeUtil.ONE_SECOND_LONG_VALUE;
    
    private static final long ONLINE_TIMEOUT_UART = 60 * TimeUtil.ONE_SECOND_LONG_VALUE;
    
    private JSONArray getJSONArrayGroups(String userKey)
    {
        HeaderPair headerAuthorization = new HeaderPair(Authorization, Token + " " + userKey);
        HeaderPair headerTimeZone = new HeaderPair(Time_Zone, Epoch);
        JSONObject json = new JSONObject();       
        try {
			json.put("userToken",userKey);
		} catch (JSONException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
        //获取用户分组及分组下的设备.
        JSONObject jsonObjectResult = EspBaseApiUtil.Post(URL, json, headerAuthorization);
        //JSONObject jsonObjectResult = EspBaseApiUtil.Get(URL, headerAuthorization, headerTimeZone);
        if (jsonObjectResult != null)
        {
            try
            {
                int status = jsonObjectResult.getInt(Status);
                if (status == HttpStatus.SC_OK)
                {
                    log.debug("getJSONArrayDeviceInfo() suc");
                    JSONArray jsonArray = jsonObjectResult.getJSONArray("groups"/*Device_Groups*/);
                    return jsonArray;
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        log.warn("getJSONArrayGroups() fail");
        return null;
    }
    
    private boolean isDeviceOnline(EspDeviceType deviceType, long last_active, long currentTime)
    {
        long timeout = 0;
        switch (deviceType)
        {
            case FLAMMABLE:
                timeout = ONLINE_TIMEOUT_GAS_SIREN;
                break;
            case HUMITURE:
                timeout = ONLINE_TIMEOUT_TEMPERATURE;
                break;
            case VOLTAGE:
                timeout = ONLINE_TIMEOUT_VOLTAGE;
                break;
            case LIGHT:
                timeout = ONLINE_TIMEOUT_LIGHT;
                break;
            case PLUG:
                timeout = ONLINE_TIMEOUT_PLUG;
                break;
            case REMOTE:
                timeout = ONLINE_TIMEOUT_REMOTE;
                break;
            case PLUGS:
                timeout = ONLINE_TIMEOUT_PLUGS;
                break;
            case UART:
            	timeout = ONLINE_TIMEOUT_UART;
            case NEW:
                break;
            case ROOT:
                break;
        }
        /**
         * when last_active is after currentTime or currentTime - last_active <= timeout, the device is online
         */
        if (last_active >= currentTime || currentTime - last_active <= timeout)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    private List<IEspGroup> setUserServerSyncGroup(JSONArray groupsJsonArray, long currentTime)
    {
        List<IEspGroup> groupList = new ArrayList<IEspGroup>();
        List<IEspDevice> deviceList = new ArrayList<IEspDevice>();
        
        for (int gi = 0; gi < groupsJsonArray.length(); gi++)
        {
            try
            {
                JSONObject groupJSON = groupsJsonArray.getJSONObject(gi);
                
                long groupId = groupJSON.getLong("id");
                String groupName = groupJSON.getString("groupName");
                IEspGroup espGroup = BEspGroup.getInstance().alloc();
                espGroup.setId(groupId);
                espGroup.setName(groupName);                
                groupList.add(espGroup);
                
                JSONArray devicesJsonArray = groupJSON.getJSONArray("devices");
                for (int i = 0; i < devicesJsonArray.length(); i++)
                {
                    JSONObject deviceJsonObject = devicesJsonArray.getJSONObject(i);
                    // bssid
                    String bssid = deviceJsonObject.getString("bssid");
                    if (bssid.equals("") || bssid.equals("12:34:56:78:91"))
                    {
                        continue;
                    }
                    // type
                    int ptype = deviceJsonObject.getInt("ptype");
                    EspDeviceType deviceType = EspDeviceType.getEspTypeEnumBySerial(ptype);
                    if ( null == deviceType)
                    {
                        // invalid ptype
                        continue;
                    }
                    
                    // userId
                    long userId = BEspUser.getBuilder().getInstance().getUserId();
                    
                    // deviceId
                    long deviceId = Long.parseLong(deviceJsonObject.getString("id"));
                    log.debug("deviceId=" + deviceId);
                    
                    // device name
                    String deviceName = deviceJsonObject.getString("deviceName");
                    
                    // filter "device-name-"
                    if (deviceName.length() > "device-name-".length())
                    {
                        String deviceNamePre = deviceName.substring(0, "device-name-".length());
                        if (deviceNamePre.equals("device-name-"))
                        {
                            deviceName = BSSIDUtil.genDeviceNameByBSSID(bssid);
                        }
                    }
                    
                    // deviceNumber
                    String devicenumber = deviceJsonObject.getString("devicenumber");
                    // rom_version and latest_rom_version
                    String rom_version = deviceJsonObject.getString("romVersion");
                    //String latest_rom_version = deviceJsonObject.getString(Latest_Rom_Version);
                    // check isOnline
                    long updatedDate = deviceJsonObject.getLong("updatedDate") * TimeUtil.ONE_SECOND_LONG_VALUE;
                    
                    boolean isOnline = deviceJsonObject.getBoolean("online");
                    //判斷設備是否在線
                   // boolean isOnline = isDeviceOnline(deviceType, updatedDate, currentTime);
                    // set state
                    EspDeviceState deviceState = new EspDeviceState();
                    if (isOnline)
                    {
                        deviceState.addStateInternet();
                    }
                    else
                    {
                        deviceState.addStateOffline();
                    }
                    int state = deviceState.getStateValue();
                    // create device
                    IEspDevice device =
                        BEspDevice.getInstance().alloc(deviceName,
                            deviceId,
                            devicenumber,
                            bssid,
                            state,
                            ptype,
                            rom_version,
                            userId);
                    
                    long activatedTime = deviceJsonObject.getLong("activiedDate") * TimeUtil.ONE_SECOND_LONG_VALUE;
                    device.setActivatedTime(activatedTime);
                    

                    
                    if (!deviceList.contains(device))
                    {
                        deviceList.add(device);
                        espGroup.addDevice(device);
                    }
                    else
                    {
                        for (IEspDevice deviceInList : deviceList)
                        {
                            if (deviceInList.equals(device))
                            {
                                espGroup.addDevice(deviceInList);
                                break;
                            }
                        }
                    }
                }
            }
            catch (JSONException e)
            {
                e.printStackTrace();
                return groupList;
            }
        }
        
        return groupList;
    }
    
    private List<IEspDevice> getDevicesFromGroupList(List<IEspGroup> groupList)
    {
        List<IEspDevice> deviceList = new ArrayList<IEspDevice>();
        for (IEspGroup group : groupList)
        {
            List<IEspDevice> deviceListInGroup = group.getDeviceList();
            for (IEspDevice deviceInList : deviceListInGroup)
            {
                if (!deviceList.contains(deviceInList))
                {
                    deviceList.add(deviceInList);
                }
            }
        }
        return deviceList;
    }
    
    @Override
    public List<IEspDevice> doCommandDeviceSynchronizeInternet(String userKey)
    {
        List<IEspGroup> groupList = doCommandGroupSynchronizeInternet(userKey);
        if (groupList == null)
        {
            return null;
        }
        else
        {
            return getDevicesFromGroupList(groupList);
        }
    }

    @Override
    public List<IEspGroup> doCommandGroupSynchronizeInternet(String userKey)
    {
        long currentTime = EspBaseApiUtil.getUTCTimeLong();
        if (currentTime == Long.MIN_VALUE)
        {
            // the Internet is unaccessible
            return null;
        }
        //先获取用户组及其组下的设备信息.
        JSONArray groupsJsonArray = getJSONArrayGroups(userKey);
        if (groupsJsonArray == null)
        {
            return null;
        }
        else
        {
            return setUserServerSyncGroup(groupsJsonArray, currentTime);
        }
    }
    
}

